#pragma once
#include <optional>
template<typename T,size_t WIDTH,size_t HEIGHT>
class Grid
{
public:
	std::optional<T> at(size_t x,size_t y);
private:
	std::optional<T> mCells[WIDTH][HEIGHT];
};

template<typename T, size_t WIDTH, size_t HEIGHT>
inline std::optional<T> Grid<T, WIDTH, HEIGHT>::at(size_t x, size_t y)
{
	return std::optional<T>();
}


template<size_t WIDTH,size_t HEIGHT>
class Grid<std::string, WIDTH, HEIGHT>
{
public:
	std::optional<std::string> at(size_t x, size_t y);
private:
	std::optional<std::string> mCells[WIDTH][HEIGHT];
};

template<size_t WIDTH, size_t HEIGHT>
inline std::optional<std::string> Grid<std::string, WIDTH, HEIGHT>::at(size_t x, size_t y)
{
	return std::string("ABC");
}

template<typename T,size_t WIDTH, size_t HEIGHT>
class Grid<T*, WIDTH, HEIGHT>
{
public:
	Grid()
	{
		for (size_t i = 0; i < WIDTH; i++)
		{
			for (size_t j = 0; j < HEIGHT; j++)
			{
				mCells[i][j] = new T();
			}
		}
	}
	~Grid()
	{
		for (size_t i = 0; i < WIDTH; i++)
		{
			for (size_t j = 0; j < HEIGHT; j++)
			{
				delete mCells[i][j].value();
				mCells[i][j] = nullptr;
			}
		}
	}
	std::optional<T*> at(size_t x, size_t y);
private:
	std::optional<T*> mCells[WIDTH][HEIGHT];

};

template<typename T, size_t WIDTH, size_t HEIGHT>
inline std::optional<T*> Grid<T*, WIDTH, HEIGHT>::at(size_t x, size_t y)
{
	return mCells[x][y];
}


class AbsClass
{
public:
	virtual void func1() = 0;
	virtual void func2() = 0;
};

class PartAbsClass:public AbsClass
{
public:
	virtual void func1()
	{

	}
	virtual void func2() = 0;
};

class FullClass:public PartAbsClass
{
public:
	virtual void func1()
	{

	}
	virtual void func2()
	{

	}
};
